package com.spzx.payment.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.web.controller.BaseController;
import com.spzx.common.core.web.domain.AjaxResult;
import com.spzx.common.rabbit.constant.MqConst;
import com.spzx.common.rabbit.service.RabbitService;
import com.spzx.common.security.annotation.RequiresLogin;
import com.spzx.order.api.RemoteOrderInfoService;
import com.spzx.order.api.domain.OrderInfo;
import com.spzx.payment.config.AlipayConfig;
import com.spzx.payment.service.IAlipayService;
import com.spzx.payment.service.IPaymentInfoService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.math.BigDecimal;
import java.util.Map;

/**
 * ClassName: AlipayController
 * Package: com.spzx.payment.controller
 * Description:
 *
 * @Author 咚咚小圆帽
 * @Create 2025/5/13 10:17
 * @Version 1.0
 */
@Slf4j
@Controller
@RequestMapping("/alipay")
public class AlipayController extends BaseController {

    @Autowired
    private IAlipayService alipayService;

    @Autowired
    private RemoteOrderInfoService remoteOrderInfoService;

    @Autowired
    private IPaymentInfoService paymentInfoService;

    @Autowired
    private RabbitService rabbitService;

    @Operation(summary = "支付宝下单")
    @RequiresLogin
    @RequestMapping("submitAlipay/{orderNo}")
    @ResponseBody
    public AjaxResult submitAlipay(@PathVariable(value = "orderNo") String orderNo) throws AlipayApiException {
        String form = alipayService.submitAlipay(orderNo);
        System.out.println("form ======================>" + form);
        return success(form);
    }

    @RequestMapping("/callback/notify")
    @ResponseBody
    public String alipayNotify(@RequestParam Map<String, String> paramMap, HttpServletRequest request) throws AlipayApiException {
        log.info("商家服务器端接收到了支付宝发起的回调请求");
        String result = "failure";
        String outTradeNo = paramMap.get("out_trade_no");

        //签名验证
        //证书模式验签
//        AlipaySignature.rsaCertCheckV1();

        //公钥模式验签
        //使用RSA的验签方法，通过签名字符串、签名参数（经过base64解码）及支付宝公钥验证签名。
        boolean flag = AlipaySignature.rsaCheckV1(
                paramMap,
                AlipayConfig.alipay_public_key,
                AlipayConfig.charset,
                AlipayConfig.sign_type
        );
        if (!flag) {
            log.error("验签失败{}，", outTradeNo);
            //只要不是success就可以
            return result;
        }
        //反正就成功
        log.info("验签成功{}，", outTradeNo);

        //进一步验签
//        4. 需要严格按照如下描述校验通知数据的正确性：
//        a. 商家需要验证该通知数据中的 out_trade_no 是否为商家系统中创建的订单号。

        R<OrderInfo> orderInfoResult = remoteOrderInfoService.getByOrderNo(outTradeNo, SecurityConstants.INNER);
        if (R.FAIL == orderInfoResult.getCode()) {
            log.error("获取订单{}失败，", outTradeNo);
            return result;
        }
        if (orderInfoResult.getData() == null) {
            log.error("订单{}不存在，", outTradeNo);
            return result;
        }
        OrderInfo orderInfo = orderInfoResult.getData();

//        b. 判断 total_amount 是否确实为该订单的实际金额（即商户订单创建时的金额）。
        String totalAmount = paramMap.get("total_amount");
        if (orderInfo.getTotalAmount().compareTo(new BigDecimal(totalAmount)) != 0) {
            log.error("订单{}金额不一致，", outTradeNo);
            return result;
        }

//        c. 校验通知中的 seller_id（或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方（有的时候，一个商家可能有多个 seller_id/seller_email）。
        String sellerId = paramMap.get("seller_id");
        if (!"2088721063971194".equals(sellerId)) {
            log.error("订单{}商家id不一致，", outTradeNo);
            return result;
        }

//        d. 验证 app_id 是否为该商家本身。
        String appId = paramMap.get("app_id");
        if (!AlipayConfig.app_id.equals(appId)) {
            log.error("订单{}app_id不一致，", outTradeNo);
            return result;
        }

//        在支付宝的业务通知中，
//        只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时，
//        支付宝才会认定为买家付款成功。
        String tradeStatus = paramMap.get("trade_status");
        if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
            // 正常的支付成功
            //记录支付日志
            log.info("记录支付日志{}",outTradeNo);
            paymentInfoService.updatePaymentStatus(paramMap, 2);
            //修改订单状态：order微服务
            //发送mq消息
            rabbitService.sendMessage(
                    MqConst.EXCHANGE_PAYMENT_PAY,
                    MqConst.ROUTING_PAYMENT_PAY,
                    outTradeNo
            );


            //扣减库存：product微服务
            //发送mq消息
            rabbitService.sendMessage(
                    MqConst.EXCHANGE_PRODUCT,
                    MqConst.ROUTING_MINUS,
                    outTradeNo
            );


            return "success";
        }



        //给支付宝响应结果，已经收到支付结果通知

        return "success";
    }

}
